package com.imddysc.spbbatchitemreadererrorrestart;

import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemStreamReader;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;


@Component("errorRestartItemStreamReader")
public class ErrorRestartItemStreamReader implements ItemStreamReader<Customer> {

	private FlatFileItemReader<Customer> customerFaltFileItemReader = new FlatFileItemReader<Customer>();
	private Long curLine = 0L;
	private boolean restart = false;
	private ExecutionContext executionContext;

	public ErrorRestartItemStreamReader() {
		customerFaltFileItemReader.setResource(new ClassPathResource("errorrestart.txt"));
		// reader.setLinesToSkip(1); //跳过第一行

		// 解析数据
		DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
		tokenizer.setNames(new String[] { "id", "firstName", "lastName", "birthday" });

		DefaultLineMapper<Customer> mapper = new DefaultLineMapper<Customer>();
		mapper.setLineTokenizer(tokenizer);
		mapper.setFieldSetMapper(new FieldSetMapper<Customer>() {

			@Override
			public Customer mapFieldSet(FieldSet fieldSet) throws BindException {
				Customer customer = new Customer();
				customer.setId(fieldSet.readLong("id"));
				customer.setFirstName(fieldSet.readString("firstName"));
				customer.setLastName(fieldSet.readString("lastName"));
				customer.setBirthday(fieldSet.readString("birthday"));
				return customer;
			}

		});

		mapper.afterPropertiesSet();
		customerFaltFileItemReader.setLineMapper(mapper);
	}

	@Override
	public void open(ExecutionContext executionContext) throws ItemStreamException {
		this.executionContext = executionContext;
		if (executionContext.containsKey("curLine")) {
			this.curLine = executionContext.getLong("curLine");
			this.restart = true;
		} else {
			this.curLine = 0L;
			executionContext.put("curLine", this.curLine);
			System.out.println("Start reading from line: " + this.curLine);
		}
	}

	@Override
	public void update(ExecutionContext executionContext) throws ItemStreamException {
		executionContext.put("curLine", this.curLine);
		System.out.println("currentLine: " + this.curLine);
	}

	@Override
	public void close() throws ItemStreamException {
		// TODO Auto-generated method stub

	}

	@Override
	public Customer read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
		Customer customer = null;
		this.curLine++;
		if (restart) {
			customerFaltFileItemReader.setLinesToSkip(this.curLine.intValue() - 1);
			restart = false;
			System.out.println("Start reading from line: " + this.curLine);
		}
		customerFaltFileItemReader.open(this.executionContext);
		customer = customerFaltFileItemReader.read();
		
		if (customer!=null && customer.getFirstName().equals("WrongName")) {
			throw new RuntimeException("Something wrong. Customer id: " + customer.getId());
		}
		
		return customer;
	}

}
